package com.dtruth.dataflow.util;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

/**
 * 
 * @author 岳海亮
 * @email yhl@feheadline.com
 * @date 2014年11月4日
 */
public class HtmlRegexpUtil {

	public static String removeComment(String htmlStr) {
		String regEx_comment = "<!--[\\s\\S]*?-->";
		Pattern p_comment = Pattern.compile(regEx_comment,
				Pattern.CASE_INSENSITIVE);
		Matcher m_comment = p_comment.matcher(htmlStr);
		htmlStr = m_comment.replaceAll(""); // 过滤注释
		return htmlStr.trim();
	}

	/**
	 * 过滤script标签以及由该标签包围的内容
	 * 
	 * @param htmlStr
	 * @return
	 */
	public static String removeScript(String htmlStr) {
		String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>";
		Pattern p_script = Pattern.compile(regEx_script,
				Pattern.CASE_INSENSITIVE);
		Matcher m_script = p_script.matcher(htmlStr);
		htmlStr = m_script.replaceAll(""); // 过滤script标签
		return htmlStr.trim();
	}

	/**
	 * 过滤Style标签以及由该标签包围的内容
	 * 
	 * @param htmlStr
	 * @return
	 */
	public static String removeStyle(String htmlStr) {
		String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>";
		Pattern p_style = Pattern
				.compile(regEx_style, Pattern.CASE_INSENSITIVE);
		Matcher m_style = p_style.matcher(htmlStr);
		htmlStr = m_style.replaceAll(""); // 过滤style标签
		return htmlStr.trim();
	}

	/**
	 * 过滤所有以"<"开头以">"结尾的标签
	 * 
	 * @param htmlStr
	 * @return
	 */
	public static String removeAllTags(String htmlStr) {
		String regEx_html = "<[^>]+?>";
		Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
		Matcher m_html = p_html.matcher(htmlStr);
		htmlStr = m_html.replaceAll(""); // 过滤html标签
		return htmlStr.trim();
	}

	public static String getValidContent(String htmlStr) {
		htmlStr = removeSpace(removeAllTags(removeStyle(removeScript(removeComment(htmlStr)))));
		htmlStr = htmlStr.replaceAll("&nbsp;", "");
		return htmlStr.trim();
	}

	/**
	 * 保留一些tags，其余的删除
	 * 
	 * @param htmlStr
	 * @param keepTags
	 * @return
	 */
	public static String removePartTags(String htmlStr, Set<String> keepTags) {
		String regEx_html = "<[^>]+?>";
		Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
		Matcher m_html = p_html.matcher(htmlStr);
		boolean result = m_html.find();
		if (result) {
			StringBuffer sb = new StringBuffer();
			do {
				String tmp = m_html.group();
				boolean flag = true;
				if (keepTags != null && keepTags.size() > 0)
					for (String keepTag : keepTags)
						if (contains(tmp, keepTag)) {
							flag = false;
							break;
						}
				if (flag)
					m_html.appendReplacement(sb, "");
				result = m_html.find();
			} while (result);
			m_html.appendTail(sb);
			return sb.toString();
		}
		m_html.reset();
		return htmlStr;
	}

	public static String removePartTagsNew(String htmlStr, Set<String> keepTags) {
		String regEx_html = "<[^>]+?>";
		Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
		Matcher m_html = p_html.matcher(htmlStr);
		boolean result = m_html.find();
		if (result) {
			StringBuffer sb = new StringBuffer();
			do {
				String tmp = m_html.group();
				if (keepTags != null && keepTags.size() > 0) {
					String tagName = getTagName(tmp);
					if (!keepTags.contains(tagName)) {
						m_html.appendReplacement(sb, "");
					}
				}
				result = m_html.find();
			} while (result);
			m_html.appendTail(sb);
			return sb.toString();
		}
		m_html.reset();
		return htmlStr;
	}

	public static String getTagName(String tagStr) {
		String reg = "<[/]*([^\\s]*)[^>]*\\s*>";
		Matcher m = Pattern.compile(reg).matcher(tagStr);
		String tagName = null;
		while (m.find()) {
			tagName = m.group(1);
		}
		m.reset();
		return tagName;
	}

	/**
	 * 是否包含某个标签
	 * 
	 * @param htmlStr
	 * @param tag
	 * @return
	 */
	public static boolean contains(String htmlStr, String tag) {
		String regxp = "</*" + tag + "[^>]*?>";
		Pattern pattern = Pattern.compile(regxp, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(htmlStr);
		return matcher.find();
	}

	/**
	 * 过滤指定标签
	 * 
	 * @param str
	 * @param tag
	 * @return
	 */
	public static String removeTags(String htmlStr, String tag) {
		String regxp = "<[/]*\\s*" + tag + "\\s+([^>]*)\\s*>";
		Pattern pattern = Pattern.compile(regxp);
		Matcher matcher = pattern.matcher(htmlStr);
		StringBuffer sb = new StringBuffer();
		boolean result1 = matcher.find();
		while (result1) {
			matcher.appendReplacement(sb, "");
			result1 = matcher.find();
		}
		matcher.appendTail(sb);
		matcher.reset();
		return sb.toString();
	}

	/**
	 * 删除空格回车标签
	 * 
	 * @param htmlStr
	 * @return
	 */
	public static String removeSpace(String htmlStr) {
		String regEx_space = "[\r|\n|\t]+";
		Pattern p_space = Pattern
				.compile(regEx_space, Pattern.CASE_INSENSITIVE);
		Matcher m_space = p_space.matcher(htmlStr);
		htmlStr = m_space.replaceAll(""); // 过滤空格回车标签
		return htmlStr.trim();
	}

	public static String removeEmoji(String htmlStr) {
		Pattern p_emoji = Pattern
				.compile(
						"[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
						Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
		Matcher m_emoji = p_emoji.matcher(htmlStr);
		htmlStr = m_emoji.replaceAll(""); // 过滤空格回车标签
		return htmlStr;

	}

	/**
	 * 删除某个标签的某个属性
	 * 
	 * @param str
	 * @param tag
	 * @param tagAttrib
	 * @return
	 */
	public static String removeTagAttribute(String str, String tag,
			String tagAttrib) {
		String regxpForTag = "<\\s*" + tag + "\\s+([^>]*\\s*)>";
		String regxpForTagAttrib = "(" + tagAttrib + "=\"[^\"]*\")";
		Pattern patternForTag = Pattern.compile(regxpForTag);
		Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
		Matcher matcherForTag = patternForTag.matcher(str);
		boolean result = matcherForTag.find();
		while (result) {
			String img = matcherForTag.group(1);
			System.out.println(img);
			Matcher matcherForAttrib = patternForAttrib.matcher(img);
			while (matcherForAttrib.find()) {
				String p = matcherForAttrib.group(1);
				str = str.replace(p, "");
			}
			result = matcherForTag.find();
		}
		return str;
	}

	/**
	 * 删除标签的所有属性
	 * 
	 * @param htmlStr
	 * @param tag
	 * @return
	 */
	public static String removeTagAllAttrib(String htmlStr, String tag) {
		String regxpForTag = "<\\s*" + tag + "\\s+[^>]*\\s*>";
		String regxpForTagAttrib = "([\\w]+)=\"[^\"]*\"";
		Pattern patternForTag = Pattern.compile(regxpForTag);
		Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
		Matcher matcherForTag = patternForTag.matcher(htmlStr);
		boolean result = matcherForTag.find();
		while (result) {
			String tagStr = matcherForTag.group();
			Matcher matcherForAttrib = patternForAttrib.matcher(tagStr);
			while (matcherForAttrib.find()) {
				String p = matcherForAttrib.group();
				htmlStr = htmlStr.replace(p, "");
			}
			matcherForAttrib.reset();
			result = matcherForTag.find();
		}
		matcherForTag.reset();
		return htmlStr.trim();
	}

	public static String getArrtibuValueFromTag(String htmlStr, String tag,
			String attr) {
		String regxpForTag = "<\\s*" + tag + "\\s+([^>]*\\s*)>";
		String regxpForTagAttrib = "" + attr + "\\s*=\"([^\"]*)\"";
		Pattern patternForTag = Pattern.compile(regxpForTag);
		Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
		Matcher matcherForTag = patternForTag.matcher(htmlStr);
		boolean result = matcherForTag.find();
		if (result) {
			String img = matcherForTag.group(1);
			Matcher matcherForAttrib = patternForAttrib.matcher(img);
			if (matcherForAttrib.find()) {
				String p = matcherForAttrib.group(1);
				return p;
			}
			matcherForAttrib.reset();
			result = matcherForTag.find();
		}
		matcherForTag.reset();
		return null;
	}

	public static List<String> getTagsWithAttrValue(String htmlStr,
			String attr, String value) {
		String regxp = "<[^>]*" + attr + "=\"(" + value + ")\"[^>]*>";
		Pattern pattern = Pattern.compile(regxp);
		Matcher matcher = pattern.matcher(htmlStr);
		List<String> list = new ArrayList<String>();
		while (matcher.find()) {
			String img = matcher.group();
			list.add(img);
		}
		matcher.reset();
		return list;
	}

	/**
	 * 删除带有链接的img标签
	 * 
	 * @param htmlStr
	 * @return
	 */
	public static String removeImgWithLink(String htmlStr, Set<String> set) {
		String reg_a = "<\\s*a\\s+[^>]*\\s*><img\\s+[^>]*\\s*></a>";
		String reg_img = "<img\\s+[^>]*\\s*>";
		Pattern pattern = Pattern.compile(reg_a);
		Pattern pattern_img = Pattern.compile(reg_img);
		Matcher matcher = pattern.matcher(htmlStr);
		while (matcher.find()) {
			String mgroup = matcher.group();
			String hrefValue = getArrtibuValueFromTag(mgroup, "a", "href");
			if (!isValidURL(hrefValue))
				continue;
			Matcher matcher_img = pattern_img.matcher(mgroup);
			if (matcher_img.find()) {
				String srcValue = getArrtibuValueFromTag(mgroup, "img",
						"[^-]src");

				if (srcValue != null) {
					set.add("http://feheadline.qiniudn.com/cont-img/"
							+ StringUtil.getMd5(srcValue));
				}
				htmlStr = htmlStr.replace(mgroup, "");
			}
			matcher_img.reset();
		}
		return htmlStr.trim();
	}

	/**
	 * 
	 * 基本功能：替换标记以正常显示
	 * <p>
	 * 
	 * @param input
	 * @return String
	 */
	public String replaceTag(String input) {
		if (!hasSpecialChars(input)) {
			return input;
		}
		StringBuffer filtered = new StringBuffer(input.length());
		char c;
		for (int i = 0; i <= input.length() - 1; i++) {
			c = input.charAt(i);
			switch (c) {
			case '<':
				filtered.append("&lt;");
				break;
			case '>':
				filtered.append("&gt;");
				break;
			case '"':
				filtered.append("&quot;");
				break;
			case '&':
				filtered.append("&amp;");
				break;
			default:
				filtered.append(c);
			}

		}
		return (filtered.toString());
	}

	/**
	 * 
	 * 基本功能：判断标记是否存在
	 * <p>
	 * 
	 * @param input
	 * @return boolean
	 */
	public boolean hasSpecialChars(String input) {
		boolean flag = false;
		if ((input != null) && (input.length() > 0)) {
			char c;
			for (int i = 0; i <= input.length() - 1; i++) {
				c = input.charAt(i);
				switch (c) {
				case '>':
					flag = true;
					break;
				case '<':
					flag = true;
					break;
				case '"':
					flag = true;
					break;
				case '&':
					flag = true;
					break;
				}
			}
		}
		return flag;
	}

	/**
	 * 
	 * 基本功能：替换指定的标签
	 * <p>
	 * 
	 * @param str
	 * @param beforeTag
	 *            要替换的标签
	 * @param tagAttrib
	 *            要替换的标签属性值
	 * @param startTag
	 *            新标签开始标记
	 * @param endTag
	 *            新标签结束标记
	 * @return String
	 * @如：替换img标签的src属性值为[img]属性值[/img]
	 */
	public static String replaceTag(String str, String beforeTag,
			String tagAttrib, String startTag, String endTag) {
		String regxpForTag = "<\\s*" + beforeTag + "\\s+([^>]*)\\s*>";
		String regxpForTagAttrib = tagAttrib + "=\"([^\"]+)\"";
		Pattern patternForTag = Pattern.compile(regxpForTag);
		Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
		Matcher matcherForTag = patternForTag.matcher(str);
		StringBuffer sb = new StringBuffer();
		boolean result = matcherForTag.find();
		while (result) {
			StringBuffer sbreplace = new StringBuffer();
			Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag
					.group(1));
			if (matcherForAttrib.find()) {
				matcherForAttrib.appendReplacement(sbreplace, startTag
						+ matcherForAttrib.group(1) + endTag);
			}
			matcherForTag.appendReplacement(sb, sbreplace.toString());
			result = matcherForTag.find();
		}
		matcherForTag.appendTail(sb);
		return sb.toString();
	}

	public static Map<String, String> getImgPath(String url, String src) {
		if (!isPicAddr(src)) {
			return null;
		}
		if (src.indexOf("data:image") > -1) {
			return null;
		}
		try {
			URI domain = new URI(URLEncoder.encode(url, "utf8"));
			String imgPath = domain.resolve(URLEncoder.encode(src, "utf8"))
					.getPath();
			URL imgURL = new URL(imgPath);
			BufferedImage bi = null;
			try {
				bi = ImageIO.read(imgURL);
			} catch (IOException e) {
				return null;
			}
			if (bi != null) {
				Map<String, String> map = new HashMap<String, String>();
				map.put("src", imgPath);
				map.put("height", bi.getHeight() + "");
				map.put("width", bi.getWidth() + "");
				return map;
			}
			return null;
		} catch (URISyntaxException | UnsupportedEncodingException
				| MalformedURLException e) {
			return null;
		}
	}

	public static boolean isPicAddr(String src) {
		String lowcase = src.trim().toLowerCase();
		if (lowcase.contains("&#x")) // 乱码图片
			return false;
		if (lowcase.endsWith(".jpg"))
			return true;
		if (lowcase.endsWith(".bmp"))
			return true;
		if (lowcase.endsWith(".jpeg"))
			return true;
		if (lowcase.endsWith(".gif"))
			return true;
		if (lowcase.endsWith(".png"))
			return true;
		return false;
	}

	public static boolean isValidURL(String input) {
		if (input == null || input.equals(""))
			return false;
		Pattern p = Pattern
				.compile(
						"^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]",
						Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(input);
		if (m.find())
			return true;
		return false;
	}

	public static String removeDisplayNone(String htmlStr, String tag) {
		String regex = "<\\s*" + tag + "\\s+([^>]*)\\s*>.*</" + tag + ">";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(htmlStr);
		while (matcher.find()) {
			String str = matcher.group();
			String value = getArrtibuValueFromTag(htmlStr, tag, "style");
			if (value == null)
				continue;
			if ("display:none;".indexOf(value) > -1) {
				htmlStr = htmlStr.replaceAll(str, "");
			}
		}
		return htmlStr;
	}

	public static void main(String[] args) {
		String htmlStr = "<img width=\"auto\" src=\"http://mmbiz.qpic.cn/mmbiz/UwiaKiaqwswthuvCqLicD46egxdWz0xedwENRRRE3N3XqxxwjNKUfQicCB2ibOWHf5y9vKiaUqft172oc1mm7VOuszsw/640?wxfrom=5&amp;tp=webp\" data-w=\"403\" data-ratio=\"0.5558312655086849\" data-s=\"300,640\" data-type=\"png\" style=\"margin: 0px; padding: 0px; box-sizing: border-box !important; word-wrap: break-word !important; width: auto !important; visibility: visible !important;\">";
		String tag = "img";
		String regxpForTag = "<\\s*" + tag + "\\s+[^>]*\\s*>";
		String regxpForTagAttrib = "([^\\s]+)=\"[^\"]*\"";
		Pattern patternForTag = Pattern.compile(regxpForTag);
		Pattern patternForAttrib = Pattern.compile(regxpForTagAttrib);
		Matcher matcherForTag = patternForTag.matcher(htmlStr);
		boolean result = matcherForTag.find();
		while (result) {
			String tagStr = matcherForTag.group();
			Matcher matcherForAttrib = patternForAttrib.matcher(tagStr);
			while (matcherForAttrib.find()) {
				String p = matcherForAttrib.group();
				System.out.println(matcherForAttrib.group(1));
				htmlStr = htmlStr.replace(p, "");
			}
			matcherForAttrib.reset();
			result = matcherForTag.find();
		}
	}
}